#include <string>
#include <iostream>
#include <map>


class Base;
class A_Base;

typedef Base* (*BaseCreateFunc)(const std::string& name);

template<typename T>
class BaseCreator
{
public:
	static Base* Create()
    {
		return new T;
    }
    static Base* Create(const std::string& name)
    {
		return new T(name);
    }
};

class Base
{
public:
    Base() { 
		a++;
		std::cout<<"base construction without ref"<<a<<"\n";
	}
    ~Base(){ a--;std::cout<<"d  base"<<a<<"\n";}
    Base(const std::string& name){	a++;std::cout<<"this is base class construction with ref , "<<name<<"-"<<a<<std::endl;}

    virtual void printSome(){ std::cout<<"Base Class--"<<a<<std::endl;}
protected:
    static int a ;
};

int Base::a = 0;

class A_Base : public Base
{
public:
    A_Base() { 
		std::cout<<"A_Base construction\n";
	}
    ~A_Base(){ std::cout<<"~ A_Base\n";}
    A_Base(const std::string& name):Base(name) { std::cout<<"A_Base construction with ref ,"<<name<<"-"<<a<<std::endl;}
    void printSome(){ std::cout<<"this is A_Base Class--"<<a<<std::endl;}
};

class CreatorMap : public std::map<std::string, BaseCreateFunc>
{
public:
	static CreatorMap & getInstance() {
		return _instance;
	}
	void set(const std::string& name, BaseCreateFunc BaseCreator)
	{
	    (*this)[name] = BaseCreator;
	}

	Base* get(const std::string& name) 
	{ 
	    BaseCreateFunc p = (*this)[name] ;
	    if (!p) {
			std::cout<<"Not find the creator for :"<<name.c_str() ;
			return NULL;
	    }
	    return p(name);
	}

	Base* get(const std::string& name, const std::string& ref) 
	{ 
	    BaseCreateFunc p = (*this)[name] ;
	    if (!p) {
		std::cout<<"Not find the creator for :"<<name.c_str() ;
		return NULL;
	    }
	    return p(ref);
	}
private:
	CreatorMap() {
		printf("CreatorMap initializer\n");
		set("base class", BaseCreator<Base>::Create); 
		set("a base class", BaseCreator<A_Base>::Create);
	}

	static CreatorMap _instance;
};

CreatorMap CreatorMap::_instance;

int main(int args , char * argc[])
{
    std::cout<<"start:\n";

    CreatorMap mCreators = CreatorMap::getInstance();

    Base* b = mCreators.get("base class");
    b->printSome();

    Base* a = mCreators.get("a base class");
    a->printSome();
}
